package client_gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;

import client.ClientSocketConnection;

import utils.Constants;
import utils.MessageViewer;
import utils.ParameterValidator;
import utils.RSA_Password;

/**
 * Klasa predstavlja dialog za promenu lozinke.
 * Klikom na dugme Change, serveru se salju parametri za promenu lozinke.
 * 
 * @author UrosKrkic & Radivoje Popovic
 */
public class ChangePasswordDialog extends JDialog implements Constants {

	
	/**
	 * Parent - prozor aplikacije.
	 */
	private ClientWindow parent;
	
	
	private JPanel jContentPane = null;
	
	
	/**
	 * LayoutManager.
	 */
	private GridBagLayout gridBag = null;
	
	
	// ogranicenja komponenti u GridBagLayout manager-u
	private GridBagConstraints oldPasswordLabelConstraint = null;
	private GridBagConstraints oldPasswordFieldConstraint = null;
	private GridBagConstraints newPasswordLabelConstraint = null;
	private GridBagConstraints newPasswordFieldConstraint = null;
	private GridBagConstraints confirmPasswordLabelConstraint = null;
	private GridBagConstraints confirmPasswordFieldConstraint = null;

	
	
	
	/**
	 * Password panel.
	 */
	private JPanel changePasswordPanel = null;
	
	
	/**
	 * Panel sa dugmadima.
	 */
	private JPanel buttonPanel = null;
	
	
	// komponente AddUserialog-a
	private JLabel oldPasswordLabel = null;
	private JPasswordField oldPasswordField = null;
	private JLabel newPasswordLabel = null;
	private JPasswordField newPasswordField = null;
	private JLabel confirmPasswordLabel = null;
	private JPasswordField confirmPasswordField = null;

	private JButton changePasswordButton = null;
	private JButton cancelButton = null;

	
	/**
	 * Dimenzije Username field-a
	 */
	private Dimension fieldDimension = new Dimension(150,20);

	
	/**
	 * Stari password.
	 */
	private String oldPassword;
	
	
	/**
	 * Novi password.
	 */
	private String newPassword;
	
	
	/**
	 * RSA algoritam za kriptovanje lozinki.
	 */
	private RSA_Password rsa = new RSA_Password();
	
	

	/**
	 * Konstruktor.
	 * @param parent - prozor aplikacije
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public ChangePasswordDialog(ClientWindow parent) {
		super(parent, "Change Password", true);
		
		this.parent = parent;
		
		this.gridBag = new GridBagLayout();
		
		oldPasswordLabelConstraint = new GridBagConstraints();
		oldPasswordFieldConstraint = new GridBagConstraints();
		newPasswordLabelConstraint = new GridBagConstraints();
		newPasswordFieldConstraint = new GridBagConstraints();
		confirmPasswordLabelConstraint = new GridBagConstraints();
		confirmPasswordFieldConstraint = new GridBagConstraints();
		
		initializeConstraints();
		
		initialize();
	}
	
	
	
	/**
	 * Metod vrsi inicijalizaciju dialoga.
	 * @author UrosKrkic & Radivoje Popovic
	 */
	private void initialize() {
		this.setSize(300, 200);
		this.setLocation(parent.getX() + parent.getWidth() / 2 - this.getWidth() / 2, parent.getY() + parent.getHeight() / 2 - this.getHeight() / 2);
		this.setResizable(false);
		this.setContentPane(getJContentPane());
		
		this.setIconImage(parent.getIconImage());
	}
	
	
	/**
	 * Metod vrsi inicijalizaciju ogranicenja komponenti u GridBagLayout manager-u.
	 * @author UrosKrkic & Radivoje Popovic
	 */
	private void initializeConstraints() {
		oldPasswordLabelConstraint.gridx = 0;
		oldPasswordLabelConstraint.gridy = 0;
		oldPasswordLabelConstraint.weightx = 1;
		oldPasswordLabelConstraint.weighty = 1;
		oldPasswordLabelConstraint.anchor = GridBagConstraints.NORTHWEST;
		oldPasswordLabelConstraint.insets = new Insets(10,10,0,0);
		
		oldPasswordFieldConstraint.gridx = 1;
		oldPasswordFieldConstraint.gridy = 0;
		oldPasswordFieldConstraint.weightx = 1;
		oldPasswordFieldConstraint.weighty = 1;
		oldPasswordFieldConstraint.anchor = GridBagConstraints.NORTHWEST;
		oldPasswordFieldConstraint.insets = new Insets(10,10,0,0);
		
		newPasswordLabelConstraint.gridx = 0;
		newPasswordLabelConstraint.gridy = 1;
		newPasswordLabelConstraint.weightx = 1;
		newPasswordLabelConstraint.weighty = 1;
		newPasswordLabelConstraint.anchor = GridBagConstraints.NORTHWEST;
		newPasswordLabelConstraint.insets = new Insets(10,10,0,0);
		
		newPasswordFieldConstraint.gridx = 1;
		newPasswordFieldConstraint.gridy = 1;
		newPasswordFieldConstraint.weightx = 1;
		newPasswordFieldConstraint.weighty = 1;
		newPasswordFieldConstraint.anchor = GridBagConstraints.NORTHWEST;
		newPasswordFieldConstraint.insets = new Insets(10,10,0,0);
		
		confirmPasswordLabelConstraint.gridx = 0;
		confirmPasswordLabelConstraint.gridy = 2;
		confirmPasswordLabelConstraint.weightx = 1;
		confirmPasswordLabelConstraint.weighty = 1;
		confirmPasswordLabelConstraint.anchor = GridBagConstraints.NORTHWEST;
		confirmPasswordLabelConstraint.insets = new Insets(10,10,0,0);
		
		confirmPasswordFieldConstraint.gridx = 1;
		confirmPasswordFieldConstraint.gridy = 2;
		confirmPasswordFieldConstraint.weightx = 1;
		confirmPasswordFieldConstraint.weighty = 1;
		confirmPasswordFieldConstraint.anchor = GridBagConstraints.NORTHWEST;
		confirmPasswordFieldConstraint.insets = new Insets(10,10,0,0);
	}
	
	
	
	
	// Metode koje inicijalizuju komponente dialoga.
	
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			
			jContentPane.setLayout(new BorderLayout());
			
			jContentPane.add(getPasswordPanel(), BorderLayout.CENTER);
			jContentPane.add(getButtonPanel(), BorderLayout.SOUTH);
		}
		
		return jContentPane;
	}
	
	
	private JPanel getPasswordPanel() {
		if (changePasswordPanel == null) {
			changePasswordPanel = new JPanel();
			
			changePasswordPanel.setLayout(gridBag);
			
			TitledBorder titledBorder = BorderFactory.createTitledBorder(BorderFactory.
					createEtchedBorder(EtchedBorder.RAISED),
					"Change Password", javax.swing.border.TitledBorder.CENTER,
					javax.swing.border.TitledBorder.DEFAULT_POSITION,
					null, null);
			
			changePasswordPanel.setBorder(titledBorder);
			
			changePasswordPanel.add(getOldPasswordLabel());
			changePasswordPanel.add(getOldPasswordField());
			changePasswordPanel.add(getNewPasswordLabel());
			changePasswordPanel.add(getNewPasswordField());
			changePasswordPanel.add(getConfirmPasswordLabel());
			changePasswordPanel.add(getConfirmPasswordField());
		}
		
		return changePasswordPanel;
	}
	
	
	private JPanel getButtonPanel() {
		if (buttonPanel == null) {
			buttonPanel = new JPanel();
			FlowLayout bpFlow = new FlowLayout(FlowLayout.CENTER);
			bpFlow.setHgap(20);
			buttonPanel.setLayout(bpFlow);
			
			buttonPanel.add(getChangePasswordButton());
			buttonPanel.add(getCancelButton());
		}
		
		return buttonPanel;
	}
	
	
	
	private JButton getChangePasswordButton() {
		if (changePasswordButton == null) {
			changePasswordButton = new JButton("Change");
			changePasswordButton.setPreferredSize(new Dimension(100,24));
			changePasswordButton.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					
					oldPassword = new String(oldPasswordField.getPassword());
					newPassword = new String(newPasswordField.getPassword());
					String confirmPassword = new String(confirmPasswordField.getPassword());
					
					oldPassword = rsa.codeData(oldPassword);

					if ( !oldPassword.equals(parent.getApplicaton().getClientUser().getPassword()) ) {
						MessageViewer.showError(parent, "Wrong old password!");
						return;
					}
					
					ParameterValidator.setRegex(ParameterValidator.passwordRegExp);
					boolean flag = ParameterValidator.matchStrings(newPassword);
					
					if (flag == false) {
						MessageViewer.showError(parent, "Bad or too long Password (max. 15 chars.)");
						return;
					}
					
					if ( !newPassword.equals(confirmPassword) ) {
						MessageViewer.showError(parent, "Password and Confirmed password must be the same.");
						return;
					}
					
					newPassword = rsa.codeData(newPassword);
					
					changePassword();
					
					ChangePasswordDialog.this.dispose();
				}
			});
		}
		
		return changePasswordButton;
	}
	
	
	
	private void changePassword() {
		ClientSocketConnection connection = parent.getApplicaton().retrieveSocketConnection();
		StringBuffer buffer = new StringBuffer();
		
		buffer.append("CHPSWD ");
		buffer.append(parent.getApplicaton().getClientUser().getUsername());
		buffer.append(" ");
		buffer.append(newPassword);
		
		String completedPasswordInfo = buffer.toString();
		
		connection.setMessage(CHPSWD_CMD, completedPasswordInfo);
		
		String response;
		
		response = connection.buffers[CHPSWD_CMD].read();
		
		if ( response.startsWith("100") ) {
			
			parent.getApplicaton().getClientUser().setPassword(newPassword);
		}
		
	}
	
	

	private JButton getCancelButton() {
		if (cancelButton == null) {
			cancelButton = new JButton("Cancel");
			cancelButton.setPreferredSize(new Dimension(100,24));
			
			cancelButton.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					ChangePasswordDialog.this.dispose();
				}
			});
		}
		
		return cancelButton;
	}
	
	
	private JLabel getOldPasswordLabel() {
		if (oldPasswordLabel == null) {
			oldPasswordLabel = new JLabel("Old Password:");
			gridBag.setConstraints(oldPasswordLabel, oldPasswordLabelConstraint);
		}
		
		return oldPasswordLabel;
	}
	
	
	private JTextField getOldPasswordField() {
		if (oldPasswordField == null) {
			oldPasswordField = new JPasswordField();
			oldPasswordField.setPreferredSize(fieldDimension);
			gridBag.setConstraints(oldPasswordField, oldPasswordFieldConstraint);
			oldPasswordField.addKeyListener(new KeyAdapter() {
				public void keyPressed(KeyEvent e) {
					if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
						cancelButton.doClick();
					}
				}
			});
		}
		
		return oldPasswordField;
	}
	
	
	private JLabel getNewPasswordLabel() {
		if (newPasswordLabel == null) {
			newPasswordLabel = new JLabel("New Password:");
			gridBag.setConstraints(newPasswordLabel, newPasswordLabelConstraint);
		}
		
		return newPasswordLabel;
	}
	
	
	private JTextField getNewPasswordField() {
		if (newPasswordField == null) {
			newPasswordField = new JPasswordField();
			newPasswordField.setPreferredSize(fieldDimension);
			gridBag.setConstraints(newPasswordField, newPasswordFieldConstraint);
			newPasswordField.addKeyListener(new KeyAdapter() {
				public void keyPressed(KeyEvent e) {
					if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
						cancelButton.doClick();
					}
				}
			});
		}
		
		return newPasswordField;
	}
	
	
	private JLabel getConfirmPasswordLabel() {
		if (confirmPasswordLabel == null) {
			confirmPasswordLabel = new JLabel("Confirm Password:");
			gridBag.setConstraints(confirmPasswordLabel, confirmPasswordLabelConstraint);
		}
		
		return confirmPasswordLabel;
	}
	
	
	private JTextField getConfirmPasswordField() {
		if (confirmPasswordField == null) {
			confirmPasswordField = new JPasswordField();
			confirmPasswordField.setPreferredSize(fieldDimension);
			gridBag.setConstraints(confirmPasswordField, confirmPasswordFieldConstraint);
			confirmPasswordField.addKeyListener(new KeyAdapter() {
				public void keyPressed(KeyEvent e) {
					if (e.getKeyCode() == KeyEvent.VK_ENTER) {
						changePasswordButton.doClick();
					} else
					if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
						cancelButton.doClick();
					}
				}
			});
		}
		
		return confirmPasswordField;
	}
	
}
